﻿namespace ScrumFactory.Data.Sql.Tests
{
    using System.Configuration;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using ScrumFactory.Data.Sql;
    using System.Transactions;
    using System.Collections.Generic;

    [TestClass()]
    public class SqlBacklogRepositoryTest {

        [TestMethod()]
        public void RetrievesBacklogItemsForProject()
        {           
            // (1) SETUP
            var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);
            string projectUId = string.Format("{0,-36}", "TEST_PROJECT_A");

            // (2) EXECUTES
            var result = target.GetCurrentBacklog(projectUId);

            // (3) ASSERTS
            Assert.IsNotNull(result);
            Assert.AreEqual(2, result.Count);
            
            var resultItem = result.Single(i => i.BacklogItemNumber == 1);
            Assert.AreEqual(projectUId, resultItem.ProjectUId);
            Assert.AreEqual("Create project plan", resultItem.Name);           
        }

        [TestMethod()]
        public void DeletesBacklogItem()
        {
            using (var transaction = new TransactionScope())
            {
                // (1) SETUP
                var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);

                // (2) EXECUTE
                target.DeleteBacklogItem("c8af565f-e181-475c-b6bd-aa27c0cd78a7");

                // (3) ASSERTS
                var result = target.GetCurrentBacklog("TEST_PROJECT_A");
                Assert.IsTrue(result.Count(i => i.BacklogItemNumber == 1) == 0);
            }
        }

     
        [TestMethod()]
        public void InsertsBacklogItem() {
            using (var transaction = new TransactionScope()) {
                
                // (1) SETUP
                var newItem = NewItem;                
                newItem.PlannedHours = new List<PlannedHour>() { PlannedHour0, PlannedHour1 };
                var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);

                // (2) EXECUTE
                target.SaveBacklogItem(newItem);

                // (3) ASSERT
                var resultItem = target.GetBacklogItem(newItem.BacklogItemUId);
                
                // item was inserted
                Assert.IsNotNull(resultItem, "Item was not inserted");

                // hours was inserted
                Assert.IsTrue(resultItem.PlannedHours.Any(h =>
                    h.BacklogItemUId == newItem.PlannedHours.ElementAt(0).BacklogItemUId &&
                    h.PlanningNumber == newItem.PlannedHours.ElementAt(0).PlanningNumber &&
                    h.RoleUId == newItem.PlannedHours.ElementAt(0).RoleUId &&
                    h.Hours == newItem.PlannedHours.ElementAt(0).Hours), "PlannedHour 0 was not inserted");

                Assert.IsTrue(resultItem.PlannedHours.Any(h =>
                    h.BacklogItemUId == newItem.PlannedHours.ElementAt(1).BacklogItemUId &&
                    h.PlanningNumber == newItem.PlannedHours.ElementAt(1).PlanningNumber &&
                    h.RoleUId == newItem.PlannedHours.ElementAt(1).RoleUId &&
                    h.Hours == newItem.PlannedHours.ElementAt(1).Hours), "PlannedHour 1 was not inserted");
                
            }
        }

        [TestMethod()]
        public void UpdatesBacklogItem()
        {
            using (var transaction = new TransactionScope())
            {
                // (1) SETUPS
                var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);
                                
                // (2) EXECUTES
                var item = target.GetBacklogItem("c8af565f-e181-475c-b6bd-aa27c0cd78a7");
                item.Description = "New Description";                
                target.SaveBacklogItem(item);

                // (3) ASSERTS
                var resultItem = target.GetBacklogItem(item.BacklogItemUId);

                Assert.AreEqual(item.BacklogItemUId, resultItem.BacklogItemUId, "BacklogItemUId mismatch");
                Assert.AreEqual(item.ProjectUId, resultItem.ProjectUId, "ProjectId mismatch");
                Assert.AreEqual(item.Description, resultItem.Description, "Description mismatch");
                
            }
        }

        [TestMethod()]
        public void UpdatesBacklogItemHours() {
            using (var transaction = new TransactionScope()) {
                // (1) SETUPS
                var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);

                // get an existing item, add 2 planned hours, and save it
                var item = target.GetBacklogItem("c8af565f-e181-475c-b6bd-aa27c0cd78a7");
                item.PlannedHours = new List<PlannedHour>() { PlannedHour0, PlannedHour1 };
                item.PlannedHours.ElementAt(0).BacklogItemUId = "c8af565f-e181-475c-b6bd-aa27c0cd78a7";
                item.PlannedHours.ElementAt(1).BacklogItemUId = "c8af565f-e181-475c-b6bd-aa27c0cd78a7";
                target.SaveBacklogItem(item);

                // (2) EXECUTES

                // now change the hours (update, delete and insert)
                item.PlannedHours.ElementAt(0).Hours = 33;
                item.PlannedHours.Remove(item.PlannedHours.ElementAt(1));
                item.PlannedHours.Add(new PlannedHour() { BacklogItemUId = item.BacklogItemUId, PlanningNumber = 0, RoleUId = "TESTER", Hours = 3 });
                target.SaveBacklogItem(item);

                // (3) ASSERTS
                var resultItem = target.GetBacklogItem(item.BacklogItemUId);

                Assert.IsTrue(resultItem.PlannedHours.Count == 2, "Item hours count mismatch");
                Assert.IsTrue(resultItem.PlannedHours.Any(h =>
                    h.BacklogItemUId == item.PlannedHours.ElementAt(0).BacklogItemUId &&
                    h.PlanningNumber == item.PlannedHours.ElementAt(0).PlanningNumber &&
                    h.RoleUId == item.PlannedHours.ElementAt(0).RoleUId &&
                    h.Hours == item.PlannedHours.ElementAt(0).Hours), "PlannedHour 0 was not updated");


            }
        }

        [TestMethod()]
        public void GetsBacklogItem() {            
            // (1) SETUPS
            var target = new SqlBacklogRepository(ConfigurationManager.ConnectionStrings["ScrumFactoryEntities"].ConnectionString);

            // (2) EXECUTES
            var item = target.GetBacklogItem("c8af565f-e181-475c-b6bd-aa27c0cd78a7");
            
            // (3) ASSERTS
            Assert.IsNotNull(item, "BacklogItem was not reatrived");

        }


        #region Mock Setups

        private BacklogItem NewItem {
            get {
                return new ScrumFactory.BacklogItem() {
                    BacklogItemUId = string.Format("{0,-36}", "backlogItem_1"),
                    Name = "New item",
                    ProjectUId = string.Format("{0,-36}", "TEST_PROJECT_A"),
                    Description = "New backlog item",
                    CreateDate = System.DateTime.Now
                };
            }
        }



        private PlannedHour PlannedHour0 {
            get {
                return new PlannedHour() {
                    BacklogItemUId = string.Format("{0,-36}", "backlogItem_1"),
                    RoleUId = "SCRUM MASTER",
                    PlanningNumber = 0,
                    Hours = 2
                };
            }
        }

        private PlannedHour PlannedHour1 {
            get {
                return new PlannedHour() {
                    BacklogItemUId = string.Format("{0,-36}", "backlogItem_1"),
                    RoleUId = "TEAM",
                    PlanningNumber = 0,
                    Hours = 1
                };
            }
        }
        #endregion

    }
}
